/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Noel De Palma - initial API and implementation
 ******************************************************************************/
package fr.jade.adl.nodes;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.objectweb.deployment.scheduling.component.lib.AbstractInstanceProviderTask;
import org.objectweb.fractal.adl.components.ComponentContainer;
import org.objectweb.fractal.adl.implementations.ImplementationBuilder;
import org.objectweb.fractal.adl.implementations.ImplementationCompiler;
import org.objectweb.fractal.adl.nodes.VirtualNode;
import org.objectweb.fractal.adl.nodes.VirtualNodeContainer;

/**
 * >>>> TODO: UNUSED: Replaced by fr.jade.adl.implementations.ImplementationCompiler <<<<
 * 
 * This compiler is used to analyse virtual node definition in 
 * an adl description.
 * It register in the adl context the name of the node under the bootstrap
 * key. The builder can then retrieve the virtual node name in the context.
 * @author nono
 * @contact noel.depalma@inrialpes.fr
 */
public class VirtualNodeImplementationCompiler
extends ImplementationCompiler
{
	
	@SuppressWarnings("unchecked")
  public AbstractInstanceProviderTask newCreateTask (
			final List path,
			final ComponentContainer container,
			final String name,
			final String definition,
			final Object controller, 
			final Object implementation,
			final Map context)
	{
		VirtualNode n = null;
		if (container instanceof VirtualNodeContainer) {
			n = ((VirtualNodeContainer)container).getVirtualNode();
		}
		if (n == null) {
			for (int i = path.size() - 1; i >= 0; --i) {
				if (path.get(i) instanceof VirtualNodeContainer) {
					n = ((VirtualNodeContainer)path.get(i)).getVirtualNode();
					if (n != null) {
						break;
					}
				}
			}
		}
		if (n != null) {
			
			return new RemoteCreateTask(
					builder, name, definition, controller, implementation, n.getName());
		}
		return super.newCreateTask(
				path, container, name, definition, controller, implementation, context);
	}
	
	static class RemoteCreateTask extends AbstractInstanceProviderTask {
		
		ImplementationBuilder builder;
		
		String name;
		
		String definition;
		
		Object controllerDesc;
		
		Object contentDesc;
		
		String node;
		
		public RemoteCreateTask (
				final ImplementationBuilder builder,
				final String name,
				final String definition,
				final Object controllerDesc,
				final Object contentDesc,
				final String node) 
		{
			this.builder = builder;
			this.name = name;
			this.definition = definition;
			this.controllerDesc = controllerDesc;
			this.contentDesc = contentDesc;
			this.node = node;
		}
		
		@SuppressWarnings("unchecked")
    public void execute (Object context) throws Exception {
			if (getInstance() != null) {
				return;
			}
			if (node != null && context instanceof Map) {
				context = new HashMap((Map)context);
				((Map)context).put("physicalNode", node);
			}
			
			Object type = getFactoryProviderTask().getFactory();
			Object result = builder.createComponent(
					type, name, definition, controllerDesc, contentDesc, context);
			setInstance(result);
		}
		
		public String toString () {
			return "T" + System.identityHashCode(this) + 
			"[CreateTask(" + name + "," + controllerDesc + "," + contentDesc + ")]";
		}
	}
}
